#include "ogreapplication.h"

#include <CEGUI/CEGUISchemeManager.h>
#include <CEGUI/CEGUIBase.h>


using namespace Ogre;
using namespace std;

namespace
{
    void
    parseResourceLocationFrom(const String& resourcesFileName)
    {
        // Load resource paths from config file
        ConfigFile cf;
        cf.load(resourcesFileName);
        // Go through all sections & settings in the file
        ConfigFile::SectionIterator seci = cf.getSectionIterator();
        while (seci.hasMoreElements())
        {
            String secName = seci.peekNextKey();
            ConfigFile::SettingsMultiMap* settings = seci.getNext();
            for (ConfigFile::SettingsMultiMap::iterator i = settings->begin();
                    i != settings->end(); ++i)
            {
                String typeName = i->first;
                String archName = i->second;
                ResourceGroupManager::getSingleton().addResourceLocation(
                    archName, typeName, secName);
            }
        }
    }
}
//************************************************************
// Implementation of OgreApplication
//************************************************************
OgreApplication::OgreApplication(Ogre::String name)
        : mName(name)
        , mRoot(NULL)
        , mWindow(NULL)
        , mEventProcessor(NULL)
        , mGUIRenderer(NULL)
        , mGUISystem(NULL)
        , mEditorGuiSheet(NULL)
        , move(Vector3(0,0,0))
        , mSelected(NULL)
        , mPrecSelected(NULL)
        , fic(NULL)
        , ov(NULL)
        , mQuitRequested(false)
{}
OgreApplication::~OgreApplication()
{
    if (mEventProcessor) delete mEventProcessor;
    if (mTrackball)      delete mTrackball;
    if (mGUISystem)      delete mGUISystem;
    if (mGUIRenderer)    delete mGUIRenderer;
    if (mRoot)           delete mRoot;
}
void
OgreApplication::addResourceLocationFrom(const String& fileName)
{
    mResourcesFileNames.push_back(fileName);
}
void
OgreApplication::create(const String& pluginsFileName,
                        const String& configFileName,
                        const String& logFileName,
                        SceneType sceneType)
{
    //////////////////////////////////////////////////////////////
    // Initialization of Root and RenderWindow
    //////////////////////////////////////////////////////////////
    mRoot = new Root(pluginsFileName,configFileName,logFileName);
    if (!mRoot->restoreConfig())
    {
        if (!mRoot->showConfigDialog())
        {
            throw Exception(0,"user quitted config dialog","OgreApplication::init()",__FILE__,__LINE__);
        }
    }
    mWindow = mRoot->initialise(true,mName);
    //////////////////////////////////////////////////////////////
    // Initializing resources
    //////////////////////////////////////////////////////////////
    for_each(mResourcesFileNames.begin(),mResourcesFileNames.end(),parseResourceLocationFrom);
    ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
    //////////////////////////////////////////////////////////////
    // Initialization of Scene
    //////////////////////////////////////////////////////////////
    mSceneManager = mRoot->createSceneManager(sceneType,"sceneManager");
    mCamera = mSceneManager->createCamera("Camera");
    mCamera->setPosition(Vector3(0.0f,0.0f,500.0f));
    mCamera->lookAt(Vector3(0.0f,0.0f,0.0f));
    mCamera->setNearClipDistance(5.0f);
    mCamera->setFarClipDistance(5000.0f);
    ////////////////////////////////////////////////////////////
    // Binding of Scene and RenderWindow
    ////////////////////////////////////////////////////////////
    mViewport = mWindow->addViewport(mCamera);
    mViewport->setBackgroundColour(ColourValue(0.0f,0.0f,0.0f));
    mCamera->setAspectRatio(Real(mViewport->getActualWidth()) /
                            Real(mViewport->getActualHeight()));
    ////////////////////////////////////////////////////////////
    // Initialize GUI
    ////////////////////////////////////////////////////////////
    mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow,Ogre::RENDER_QUEUE_OVERLAY,
                   false,3000,
                   mSceneManager);
    mGUISystem = new CEGUI::System(mGUIRenderer);
    CEGUI::SchemeManager::getSingleton().loadScheme((CEGUI::utf8*)"TaharezLookSkin.scheme");
    mGUISystem->setDefaultMouseCursor(reinterpret_cast<const CEGUI::utf8*>("TaharezLook"),
                                      reinterpret_cast<const CEGUI::utf8*>("MouseArrow"));
    CEGUI::MouseCursor::getSingleton().setImage(CEGUI::System::getSingleton().getDefaultMouseCursor());
    mGUISystem->setDefaultFont((CEGUI::utf8*)"BlueHighway-12");
    mEditorGuiSheet= CEGUI::WindowManager::getSingleton().loadWindowLayout((CEGUI::utf8*)"visage.layout");
    mGUISystem->setGUISheet(mEditorGuiSheet);
    ////////////////////////////////////////////////////////////
    // Managing input
    ////////////////////////////////////////////////////////////
    mRoot->addFrameListener(this);

    mTrackball = new Trackball(mGUIRenderer,mGUISystem,mCamera,mSceneManager);

    mEventProcessor = new EventProcessor();
    mEventProcessor->addKeyListener(this);
    mEventProcessor->addMouseListener(mTrackball);
    mEventProcessor->addMouseMotionListener(mTrackball);
    CEGUI::Combobox* listeOV = (CEGUI::Combobox*)CEGUI::WindowManager::getSingleton().getWindow("VisageGui/ChoixOV");
    CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem((CEGUI::utf8*)"FrameWindow", 0);

    item = new CEGUI::ListboxTextItem((CEGUI::utf8*)"Orga One - /mnt", 0);
    listeOV->addItem(item);
    item = new CEGUI::ListboxTextItem((CEGUI::utf8*)"Orga Two - /src", 1);
    listeOV->addItem(item);

    CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
    static_cast<CEGUI::StaticImage*>(wmgr.getWindow((CEGUI::utf8*)"VisageGui/Options/CPallier1"))->setImageColours(CEGUI::colour(1,0,0));
    static_cast<CEGUI::StaticImage*>(wmgr.getWindow((CEGUI::utf8*)"VisageGui/Options/CPallier2"))->setImageColours(CEGUI::colour(0,1,0));
    static_cast<CEGUI::StaticImage*>(wmgr.getWindow((CEGUI::utf8*)"VisageGui/Options/CPallier3"))->setImageColours(CEGUI::colour(0,0,1));
    //wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control")->subscribeEvent(CEGUI::Window::EventMouseButtonUp, CEGUI::Event::Subscriber(&OgreApplication::handleDisable, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control/Quit")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handleQuit, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control/Options")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handleOptions, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Options/Annuler")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handleCancelOptions, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control/Racine")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handleRacine, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control/OV")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handleOV, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/ChoixOV")->subscribeEvent(CEGUI::Combobox::EventListSelectionAccepted, CEGUI::Event::Subscriber(&OgreApplication::handleChoixOV, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control/Parent")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handleParent, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Outils/FiltreTaille")->subscribeEvent(CEGUI::Scrollbar::EventScrollPositionChanged, CEGUI::Event::Subscriber(&OgreApplication::handleFiltreTaille, this));
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Control/Precedent")->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&OgreApplication::handlePrecedent, this));
    //////////////////////////////////////////////////////////////
    //  User initialization (subclassed)
    //////////////////////////////////////////////////////////////
    init();
}
void
OgreApplication::run()
{
    mEventProcessor->initialise(mWindow);
    mEventProcessor->startProcessingEvents();
    mRoot->startRendering();
}
void
OgreApplication::keyClicked(KeyEvent *e)
{}
void
OgreApplication::keyPressed(KeyEvent *e)
{}
void
OgreApplication::keyReleased(KeyEvent *e)
{}
bool
OgreApplication::frameStarted(const FrameEvent& evt)
{
    return true;
}
bool
OgreApplication::frameEnded(const FrameEvent& evt)
{

    mCamera->moveRelative(move);

    return !mQuitRequested;
}
void
OgreApplication::init()
{}
void
OgreApplication::requestQuit()
{
    mQuitRequested = true;
}
bool OgreApplication::handleQuit(const CEGUI::EventArgs& e)
{
    mQuitRequested = true;
    return true;
}

bool OgreApplication::handleOptions(const CEGUI::EventArgs& e)
{
    CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/FOptions")->setVisible(true);
    return true;
}

bool OgreApplication::handleCancelOptions(const CEGUI::EventArgs& e)
{
    CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/FOptions")->setVisible(false);
    return true;
}


bool OgreApplication::handleRacine(const CEGUI::EventArgs& e)
{

    /*//mSelected = (Entity*) (fic->setCaption(mSceneManager->getRootSceneNode()->;
    //mSelected->getParentSceneNode()->showBoundingBox(true);
    //fic->setCaption("Nom du fichier: " + mSelected->getName());

    mTrackball->mSelected = mSceneManager->getEntity("Rep1");
    mTrackball->mSelected->getParentSceneNode()->showBoundingBox(true);
    fic->setCaption("Nom du fichier: " + mTrackball->mSelected->getName());
    mCamera->setPosition(mTrackball->mSelected->getParentNode()->getWorldPosition() + Vector3(0,0,500));
    mCamera->lookAt(mTrackball->mSelected->getParentNode()->getWorldPosition());*/
    return true;
}

bool OgreApplication::handleOV(const CEGUI::EventArgs& e)
{
    CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/ChoixOV")->setVisible(true);
    return true;
}

bool OgreApplication::handleChoixOV(const CEGUI::EventArgs& e)
{
    const CEGUI::WindowEventArgs& windowEventArgs = static_cast<const CEGUI::WindowEventArgs&>(e);
    CEGUI::ListboxItem* item = static_cast<CEGUI::Combobox*>(windowEventArgs.window)->getSelectedItem();
    CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/ChoixOV")->setText("Choix de l'organisation virtuelle");
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/ChoixOV")->setVisible(false);
    String nom = item->getText().c_str();
    String label = "Nom de l' OV : ";
    label += item->getText().c_str();
    ov->setCaption(label);
    //OVcourante = OVchoisie
    //item->getID()
    return true;
}

bool OgreApplication::handleFiltreTaille(const CEGUI::EventArgs& e)
{
    CEGUI::WindowManager& wmgr = CEGUI::WindowManager::getSingleton();
    float y = static_cast<CEGUI::Scrollbar*>(wmgr.getWindow((CEGUI::utf8*)"VisageGui/Outils/FiltreTaille"))->getScrollPosition();
    wmgr.getWindow((CEGUI::utf8*)"VisageGui/Outils/LFiltreTaille")->setText("Taille minimale : " + StringConverter::toString(y) + " ko");
    fic->setCaption(StringConverter::toString(y));
    return true;
}

bool OgreApplication::handleParent(const CEGUI::EventArgs& e)
{
   /* if (mTrackball->mPrecSelected != NULL)
    {
        mTrackball->mPrecSelected->getParentSceneNode()->showBoundingBox(false);
        if (mTrackball->mPrecSelected->getParentSceneNode()->getParentSceneNode()->numAttachedObjects() != 0)
            mTrackball->mSelected = (Entity*) (mTrackball->mPrecSelected->getParentSceneNode()->getParentSceneNode()->getAttachedObject(0));
        mTrackball->mSelected->getParentSceneNode()->showBoundingBox(true);
        fic->setCaption("Nom du fichier: " + mTrackball->mSelected->getName());
        mCamera->setPosition(mTrackball->mSelected->getParentNode()->getWorldPosition() + Vector3(0,0,500));
        mCamera->lookAt(mTrackball->mSelected->getParentNode()->getWorldPosition());


        //Utiliser nom de selected - "/nomSelected"
    }*/
    return(true);
}

bool OgreApplication::handlePrecedent(const CEGUI::EventArgs& e)
{
    //fic->setCaption(mPrecSelected->getName());

    if (mSelected != NULL)
    {
        mCamera->setPosition(mSelected->getParentNode()->getWorldPosition() + Vector3(0,0,500));
        mCamera->lookAt(mSelected->getParentNode()->getWorldPosition());

    }
    return(true);
}

bool OgreApplication::handleDisable(const CEGUI::EventArgs& e)
{
    return true;
}
